<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="tX16s" id="tX16s"><span data-lake-id="ua68c99e7" id="ua68c99e7" style="color: rgb(38, 38, 38)">典型回答</span></h1>
  <p data-lake-id="u570859d6" id="u570859d6"><span data-lake-id="u92e9e1de" id="u92e9e1de">Mybatis内置了三种数据源，分别是Pooled，Unpooled和JNDI，其中Pooled数据源是具有连接池的。同时Mybatis也可以使用三方数据源，如Druid，Hikari，C3P0等等</span></p>
  <p data-lake-id="u5e45c05a" id="u5e45c05a"><span data-lake-id="ua1d8bb2b" id="ua1d8bb2b">Mybatis数据源的类图如下所示：</span></p>
  <p data-lake-id="u51adaa8c" id="u51adaa8c"><img src="https://cdn.nlark.com/yuque/0/2023/png/719664/1684660340953-1acc1590-1b07-4df6-ad1a-9fc15936c9f3.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_42%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="ubda10111" id="ubda10111"><span data-lake-id="u42a1b8c2" id="u42a1b8c2">可以看到，在Mybatis中，会通过工厂模式来获得对应的数据源，那么Mybatis是在执行的哪一步获取的呢？<br></span><span data-lake-id="ue8590054" id="ue8590054">答案是在执行SQL之前，Mybatis会获取数据库连接Connection，而此时获得的Connection则是应用的启动的时候，已经通过配置项中的文件加载到内存中了：</span></p>
  <pre lang="java"><code>
&lt;dataSource type="org.apache.ibatis.datasource.pooled.PooledDataSource"&gt;
  &lt;property name="driver" value="com.mysql.jdbc.Driver"/&gt;
  &lt;property name="url" value="jdbc:mysql://localhost:3306/mybatis"/&gt;
  &lt;property name="username" value="root"/&gt;
  &lt;property name="password" value="123456"/&gt;
&lt;/dataSource&gt;
</code></pre>
  <p data-lake-id="uaa50e7f6" id="uaa50e7f6"><span data-lake-id="u5c83a535" id="u5c83a535">一般情况下，我们不会使用Mybatis默认的PooledDataSource，而是会用Hikari，如果要增加Sql监控功能的话，也可以使用Druid，这是因为自带的数据库连接池有三个缺点：</span></p>
  <ol list="u3924fa63">
   <li fid="u23ae44f0" data-lake-id="u85dd490f" id="u85dd490f"><span data-lake-id="u5baf9fc4" id="u5baf9fc4">空闲连接占用资源：连接池维护一定数量的空闲连接，这些连接会占用系统的资源，如果连接池设置过大，那么会浪费系统资源，如果设置过小，则会导致系统并发请求时连接不够用，影响系统性能。</span></li>
   <li fid="u23ae44f0" data-lake-id="u0828d6cd" id="u0828d6cd"><span data-lake-id="u7a2572ba" id="u7a2572ba">连接池大小调优困难：连接池的大小设置需要根据系统的并发请求量、数据库的性能和系统的硬件配置等因素综合考虑，而这些因素都是难以预测和调整的。</span></li>
   <li fid="u23ae44f0" data-lake-id="u3aaedd65" id="u3aaedd65"><span data-lake-id="u135b565c" id="u135b565c">连接泄漏：如果应用程序没有正确关闭连接，那么连接池中的连接就会泄漏，导致连接池中的连接数量不断增加，最终导致系统崩溃。</span></li>
  </ol>
  <p data-lake-id="u0dc3acf0" id="u0dc3acf0"><span data-lake-id="u81c41988" id="u81c41988">总的来说，专业的事情交给专业的组件来做，Mybatis功能的核心是ORM映射和缓存，数据库连接池这种东西，市场上已经有比它做的更好的，我们直接用那些更好的就行了。</span></p>
  <h1 data-lake-id="j3JPo" id="j3JPo"><span data-lake-id="uf10d4bc8" id="uf10d4bc8">知识扩展</span></h1>
  <h2 data-lake-id="N19Kn" id="N19Kn"><span data-lake-id="ue4ce418e" id="ue4ce418e">什么是数据源，数据库和数据库连接池？</span></h2>
  <p data-lake-id="u5331f3e3" id="u5331f3e3"><span data-lake-id="ua8edd9c8" id="ua8edd9c8">一般应用程序在连接数据库的时候，会有三步：</span></p>
  <ol list="u71c15999">
   <li fid="ub7cc6d40" data-lake-id="u8e909c15" id="u8e909c15"><span data-lake-id="ubced4fd7" id="ubced4fd7">输入url，name，pwd产生一个connection</span></li>
   <li fid="ub7cc6d40" data-lake-id="u6d756f3f" id="u6d756f3f"><span data-lake-id="u89ae4d91" id="u89ae4d91">然后在这个connection中完成对应的sql操作</span></li>
   <li fid="ub7cc6d40" data-lake-id="u3bc2bb49" id="u3bc2bb49"><span data-lake-id="u0e069fd8" id="u0e069fd8">完成事务的提交或者回滚</span></li>
  </ol>
  <p data-lake-id="uf9423a8a" id="uf9423a8a"><span data-lake-id="u10032831" id="u10032831">为了对这三步进行抽象，诞生了数据源的概念，一般被定义为DataSource。数据源负责和实体数据库的连接，如（内存数据库，mysql等），所以数据源是被第三方数据库实现的。同时，因为通过数据源对数据库操作做了抽象，我们也可以在数据源中完成对数据库连接的池化，这就是数据库连接池。</span></p>
  <p data-lake-id="u9dab6a5c" id="u9dab6a5c"><span data-lake-id="u37c54c0b" id="u37c54c0b">借用javaDoc对</span><code data-lake-id="u01a1c4ab" id="u01a1c4ab"><span data-lake-id="u46fbe0bf" id="u46fbe0bf">DataSource</span></code><span data-lake-id="u3c9d35ff" id="u3c9d35ff">的注释：</span></p>
  <blockquote data-lake-id="u6c76f840" id="u6c76f840">
   <p data-lake-id="u0d714615" id="u0d714615"><span data-lake-id="u2678160c" id="u2678160c">数据源用于连接到此DataSource对象所表示的物理数据源的工厂。作为DriverManager功能的替代方案，DataSource对象是获取连接的首选方式。实现DataSource接口的对象通常会向基于Java的命名服务注册™ 命名和目录（JNDI）API。</span></p>
   <p data-lake-id="udc07f5b6" id="udc07f5b6"><span data-lake-id="ucd986c23" id="ucd986c23">DataSource接口由驱动程序供应商实现。有三种类型的实现：</span></p>
   <ol list="u91d93137">
    <li fid="u333a70c7" data-lake-id="u8d0ed39e" id="u8d0ed39e"><span data-lake-id="u1c3b8ce6" id="u1c3b8ce6">基本实现--生成一个标准Connection对象</span></li>
    <li fid="u333a70c7" data-lake-id="uf80b8c75" id="uf80b8c75"><span data-lake-id="u3f72a060" id="u3f72a060">连接池实现--生成一个Connection对象，该对象将自动参与连接池。此实现与中间层连接池管理器一起工作。</span></li>
    <li fid="u333a70c7" data-lake-id="u4e9a0350" id="u4e9a0350"><span data-lake-id="u1f020057" id="u1f020057">分布式事务实现--生成一个Connection对象，该对象可以用于分布式事务，并且几乎总是参与连接池。此实现使用中间层事务管理器，并且几乎总是使用连接池</span></li>
   </ol>
  </blockquote>
 </body>
</html>